package meterMonitor.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonNetMapper {

	private static final Logger logger = LoggerFactory.getLogger(JacksonNetMapper.class);

	private static  ObjectMapper mapper = new ObjectMapper();

	
	private JacksonNetMapper() {

	}

	/**
	 *
	 * @return
	 */
	public static ObjectMapper getInstance() {
		
		//mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy());
		return mapper;
	}
	
	
	/**
	 * 将对象转换为JSON字符串
	 * 
	 * @param value
	 *            对象
	 * @return JSOn字符串
	 */
	public static String toJson(Object value) {
		try {
			return mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).writeValueAsString(value);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	/**
	 * 将JSON字符串转换为对象
	 * 
	 * @param json
	 *            JSON字符串
	 * @param valueType
	 *            对象类型
	 * @return 对象
	 */
	public static <T> T toObject(String json, Class<T> valueType) {
		Assert.hasText(json);
		Assert.notNull(valueType);
		try {
			return mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).readValue(json, valueType);
		} catch (Exception e) {
			e.printStackTrace();	
			logger.error("json"+json+"valueType"+valueType, e.getMessage());
		}
		return null;
	}

	/**
	 * 将JSON字符串转换为对象
	 * 
	 * @param json
	 *            JSON字符串
	 * @param typeReference
	 *            对象类型
	 * @return 对象
	 */
	public static <T> T toObject(String json, TypeReference<?> typeReference) {
		
		
		Assert.hasText(json);
		Assert.notNull(typeReference);
		try {
			return mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).readValue(json, typeReference);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将JSON字符串转换为对象
	 * 
	 * @param json
	 *            JSON字符串
	 * @param javaType
	 *            对象类型
	 * @return 对象
	 */
	public static <T> T toObject(String json, JavaType javaType) {
		Assert.hasText(json);
		Assert.notNull(javaType);
		try {
			return mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).readValue(json, javaType);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将对象转换为JSON流
	 * 
	 * @param writer
	 *            writer
	 * @param value
	 *            对象
	 */
	public static void writeValue(Writer writer, Object value) {
		try {
			mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).writeValue(writer, value);
		} catch (JsonGenerationException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 读取json串中某一个字段的值
	 * @param json
	 * @param property
	 * @return
	 */
	public static Object readValueByProperty(String json,String property){
		HashMap jsonMap = null;
		try {
			 jsonMap = mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).readValue(json, HashMap.class);
		} catch (IOException e) {
			logger.error("读取配置文件错误：" + e.getLocalizedMessage() + e.getMessage() + e.toString());
		}
		return null==jsonMap?null:jsonMap.get(property);
	}


	/**
	 * 将一个 Map 对象转化为一个 JavaBean
	 * @param type 要转化的类型
	 * @param map 包含属性值的 map
	 * @return 转化出来的 JavaBean 对象
	 * @throws IntrospectionException 如果分析类属性失败
	 * @throws IllegalAccessException 如果实例化 JavaBean 失败
	 * @throws InstantiationException 如果实例化 JavaBean 失败
	 * @throws InvocationTargetException 如果调用属性的 setter 方法失败
	 */
	@SuppressWarnings("rawtypes")
	public static Object convertMap(Class type, Map map)
			throws IntrospectionException, IllegalAccessException,
			InstantiationException, InvocationTargetException {
		BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
		Object obj = type.newInstance(); // 创建 JavaBean 对象

		// 给 JavaBean 对象的属性赋值
		PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
		for (int i = 0; i< propertyDescriptors.length; i++) {
			PropertyDescriptor descriptor = propertyDescriptors[i];
			String propertyName = descriptor.getName();

			String propertyType = descriptor.getPropertyType().toString();   //获取属性类型

			if (map.containsKey(propertyName.toUpperCase())) {
				// 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
				Object value = map.get(propertyName.toUpperCase());
				try {

					if(null == value)continue;

					Object[] args = new Object[1];

					if(propertyType.equals("class java.lang.Double")){
						args[0] = Double.valueOf(String.valueOf(value));
					}

					if(propertyType.equals("class java.lang.String")){
						args[0] = String.valueOf(value);
					}

					if(propertyType.equals("class java.util.Date")){
						args[0] = Timestamp.valueOf(String.valueOf(value));
					}

					if(propertyType.equals("class java.lang.Long")){
						args[0] = Long.valueOf(String.valueOf(value));
					}

					if(propertyType.equals("class java.lang.Integer")){
						args[0] = Integer.valueOf(String.valueOf(value));
					}

					if(propertyType.equals("class java.lang.Boolean")){
						args[0] = Boolean.valueOf(String.valueOf(value));
					}

					if(propertyType.equals("class java.math.BigDecimal")){
						args[0] = BigDecimal.valueOf(Long.valueOf(String.valueOf(value)));
					}

					if(propertyType.equals("class java.lang.Short")){
						args[0] = Short.valueOf(String.valueOf(value));
					}
					descriptor.getWriteMethod().invoke(obj, args);
				}catch (Exception e){
					logger.error("错误 ： {}",e);
				}
			}
		}
		return obj;
	}

	/**
	 * json array string convert to list with javaBean
	 */
	public static <T> List<T> jsonToList(String jsonArrayStr, Class<T> clazz)
			throws Exception {
		List<Map<String, Object>> list = mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).readValue(jsonArrayStr,
				new TypeReference<List<T>>() {
				});
		List<T> result = new ArrayList<T>();
		for (Map<String, Object> map : list) {
			result.add(mapToJavaBean(map, clazz));
		}
		return result;
	}

	/**
	 * map convert to javaBean
	 */
	 public static <T> T mapToJavaBean(Map map, Class<T> clazz) {
		  return mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).convertValue(map, clazz);
	 }

	/**
	 * json 转 Map
	 * @param json
	 * @return
	 */
	public  static Map jsonToMap(String json){
		Map maps = null;
		try {
			 maps = mapper.setPropertyNamingStrategy(new LowercasePropertyNamingStrategy()).readValue(json, Map.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return  maps;
	}
	 
}


